/**
 * 增强版客户端测试脚本 - 包含娱乐城功能测试
 * 异常时终止脚本，修复后可继续执行
 */

const http = require('http');
const WebSocket = require('ws');

const CONFIG = {
    server: {
        host: 'localhost',
        port: 3000
    },
    // server: { host: 'cdsgjs.com', port: 8206 },
    testUser: {
        mobile: '17091271111',
        passwordHash: 'e10adc3949ba59abbe56e057f20f883e'
    },
    testCharacter: { name: '测试角色', sex: 1, roleType: 1, headIndex: 2 }
};

class EnhancedClientTester {
    constructor() {
        this.token = null;
        this.userId = null;
        this.ws = null;
        this.characters = [];
        this.selectedCharacter = null;
        this.testResults = [];
        this.currentStep = 0;
        this.steps = [
            'HTTP登录', 'WebSocket连接', '查询角色', '创建角色(如需要)',
            '选择角色', '验证被动消息', '娱乐城连接', '查询期数',
            '下注测试', '猜拳测试', '查询开奖信息', '断开连接'
        ];
    }

    async runTest() {
        console.log('🚀 开始增强版客户端测试...\n');

        try {
            await this.executeStep(0, this.testHttpLogin);
            await this.executeStep(1, this.testWebSocketConnection);
            await this.executeStep(2, this.testQueryCharacters);

            if (this.characters.length === 0) {
                await this.executeStep(3, this.testCreateCharacter);
                await this.executeStep(2, this.testQueryCharacters);
            }

            await this.executeStep(4, this.testSelectCharacter);
            await this.executeStep(5, this.testPassiveMessages);
            await this.executeStep(6, this.testCasinoConnection);
            await this.executeStep(7, this.testQueryCasinoRounds);
            await this.executeStep(8, this.testCasinoBetting);
            await this.executeStep(9, this.testCasinoRockPaperScissors);
            await this.executeStep(10, this.testQueryCasinoResults); // 新增：查询开奖信息
            await this.executeStep(11, this.testDisconnect);

            this.showResults();
        } catch (error) {
            console.error(`❌ 测试在第${this.currentStep + 1}步失败: ${this.steps[this.currentStep]}`);
            console.error('错误详情:', error.message);
            console.log('\n💡 修复问题后，可以从以下命令继续执行:');
            console.log(`node demo-client-test-with-casino.js --continue-from ${this.currentStep + 1}`);
            process.exit(1);
        }
    }

    async executeStep(stepIndex, stepFunction) {
        this.currentStep = stepIndex;
        console.log(`\n🔍 步骤${stepIndex + 1}: ${this.steps[stepIndex]}...`);
        await stepFunction.call(this);
        console.log(`✅ 步骤${stepIndex + 1}完成`);
    }

    // 基础功能测试
    async testHttpLogin() {
        const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
            mobile: CONFIG.testUser.mobile,
            pwd: CONFIG.testUser.passwordHash
        });

        if (loginData.code !== 0) throw new Error(`登录失败: ${loginData.msg}`);

        this.userId = loginData.data.userId;
        this.token = loginData.data.accessToken;
        this.addTestResult('HTTP登录', true, `用户ID: ${this.userId}`);
    }

    async testWebSocketConnection() {
        return new Promise((resolve, reject) => {
            const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
            this.ws = new WebSocket(wsUrl);

            this.ws.on('open', () => {
                this.setupMessageHandler();
                this.addTestResult('WebSocket连接', true, '连接成功');
                resolve();
            });

            this.ws.on('error', reject);
            setTimeout(() => reject(new Error('连接超时')), 10000);
        });
    }

    async testQueryCharacters() {
        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 3) {
                    this.ws.removeListener('message', handler);
                    this.characters = msg.roleList || [];
                    this.addTestResult('查询角色', true, `获取${this.characters.length}个角色`);
                    resolve();
                }
            };

            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 3, d: null }));
            setTimeout(() => resolve(), 5000);
        });
    }

    async testCreateCharacter() {
        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 5 && msg.code === 0) {
                    this.ws.removeListener('message', handler);
                    this.addTestResult('创建角色', true, '角色创建成功');
                    resolve();
                }
            };

            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({
                c: 5,
                d: { name: CONFIG.testCharacter.name, sex: CONFIG.testCharacter.sex, roleType: CONFIG.testCharacter.roleType }
            }));
            setTimeout(() => resolve(), 5000);
        });
    }

    async testSelectCharacter() {
        if (this.characters.length === 0) throw new Error('没有可用角色');

        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 4 && msg.code === 0) {
                    this.ws.removeListener('message', handler);
                    this.selectedCharacter = this.characters[0];
                    this.addTestResult('选择角色', true, `选择角色: ${this.selectedCharacter.name}`);
                    setTimeout(resolve, 3000);
                }
            };

            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 4, d: { characterId: this.characters[0].id } }));
            setTimeout(() => resolve(), 10000);
        });
    }

    async testPassiveMessages() {
        await new Promise(resolve => setTimeout(resolve, 5000));
        this.addTestResult('被动消息', true, '等待完成');
    }

    // 娱乐城功能测试
    async testCasinoConnection() {
        // 娱乐城功能通过主WebSocket提供，不需要单独连接
        console.log('🎰 娱乐城功能通过主WebSocket提供，无需额外连接');
        this.addTestResult('娱乐城连接', true, '通过主WebSocket提供');
        return Promise.resolve();
    }

    async testQueryCasinoRounds() {
        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 1332) { // 查询期数响应
                    this.ws.removeListener('message', handler);
                    this.addTestResult('查询期数', true, `获取${msg.rounds?.length || 0}个期数`);
                    resolve();
                }
            };

            this.ws.on('message', handler);
            this.ws.send(JSON.stringify({ c: 1332, d: null })); // 查询大小玩法期数
            setTimeout(() => resolve(), 5000);
        });
    }

    async testCasinoBetting() {
        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 1336) { // 下注响应
                    this.ws.removeListener('message', handler);
                    if (msg.code === 0) {
                        this.addTestResult('下注测试', true, '下注成功');
                    } else {
                        this.addTestResult('下注测试', false, msg.msg);
                    }
                    resolve();
                }
            };

            this.ws.on('message', handler);
            // 发送下注请求
            this.ws.send(JSON.stringify({
                c: 1336,
                d: { action: 0, type: "3", bet: 100 }
            }));
            setTimeout(() => resolve(), 5000);
        });
    }

    async testCasinoRockPaperScissors() {
        return new Promise((resolve) => {
            const handler = (data) => {
                const msg = JSON.parse(data.toString());
                if (msg.act_id === 2110) { // 猜拳响应
                    this.ws.removeListener('message', handler);
                    if (msg.code === 0) {
                        this.addTestResult('猜拳测试', true, '猜拳成功');
                    } else {
                        this.addTestResult('猜拳测试', false, msg.msg);
                    }
                    resolve();
                }
            };

            this.ws.on('message', handler);
            // 发送猜拳请求
            this.ws.send(JSON.stringify({
                c: 2110,
                d: { value: "1", type: 1, bet: 100 }
            }));
            setTimeout(() => resolve(), 5000);
        });
    }

    // 新增：查询娱乐城开奖信息
    async testQueryCasinoResults() {
        console.log('\n🎲 查询娱乐城开奖信息...');

        return new Promise((resolve) => {
            if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
                this.addTestResult('查询开奖信息', false, 'WebSocket未连接');
                resolve();
                return;
            }

            // 设置响应监听器
            const responseHandler = (data) => {
                try {
                    const message = JSON.parse(data.toString());
                    console.log('🎲 收到娱乐城响应:', JSON.stringify(message, null, 2));

                    // 根据不同的act_id处理响应
                    if (message.act_id === 1332) { // 查询期数响应
                        this.ws.removeListener('message', responseHandler);

                        if (message.code === 0) {
                            if (message.data && message.data.rounds && message.data.rounds.length > 0) {
                                const rounds = message.data.rounds;
                                console.log(`✅ 查询开奖信息成功，获取${rounds.length}个期数信息`);

                                // 显示开奖信息详情
                                rounds.forEach((round, index) => {
                                    console.log(`\n📊 期数${index + 1}:`);
                                    console.log(`   期数ID: ${round.id}`);
                                    console.log(`   游戏类型: ${round.gameType}`);
                                    console.log(`   状态: ${this.getRoundStatusText(round.status)}`);
                                    console.log(`   开始时间: ${round.startTime}`);
                                    console.log(`   结束时间: ${round.endTime}`);
                                    console.log(`   开奖结果: ${round.resultData || '未开奖'}`);
                                    console.log(`   下注总额: ${round.totalBetAmount || 0}`);
                                    console.log(`   参与人数: ${round.participantCount || 0}`);
                                });

                                this.addTestResult('查询开奖信息', true, `获取${rounds.length}个期数信息`);
                            } else {
                                console.log('✅ 查询开奖信息成功，但当前没有期数数据');
                                console.log('💡 可能原因：');
                                console.log('   • 娱乐城系统刚启动，还未生成期数');
                                console.log('   • 定时任务未正常运行');
                                console.log('   • 数据库中没有期数记录');

                                this.addTestResult('查询开奖信息', true, '查询成功，暂无期数数据');
                            }
                        } else {
                            console.log(`❌ 查询开奖信息失败: ${message.msg || '未知错误'}`);
                            this.addTestResult('查询开奖信息', false, message.msg || '查询失败');
                        }
                        resolve();
                    }
                } catch (error) {
                    console.error('❌ 娱乐城响应解析失败:', error.message);
                    this.ws.removeListener('message', responseHandler);
                    this.addTestResult('查询开奖信息', false, '响应解析失败');
                    resolve();
                }
            };

            this.ws.on('message', responseHandler);

            // 发送查询开奖信息请求
            const queryRequest = {
                c: 1332, // 查询期数指令
                d: null
            };

            console.log('📤 发送查询开奖信息请求:', JSON.stringify(queryRequest, null, 2));
            this.ws.send(JSON.stringify(queryRequest));

            // 设置超时
            setTimeout(() => {
                this.ws.removeListener('message', responseHandler);
                this.addTestResult('查询开奖信息', false, '请求超时');
                resolve();
            }, 10000);
        });
    }

    // 新增：设置娱乐城消息处理器
    setupCasinoMessageHandler() {
        // 娱乐城消息通过主WebSocket处理，无需额外设置
    }

    // 新增：获取期数状态文本
    getRoundStatusText(status) {
        const statusMap = {
            0: '下注中',
            1: '开奖中',
            2: '已结算',
            3: '已取消'
        };
        return statusMap[status] || `未知状态(${status})`;
    }

    async testDisconnect() {
        if (this.ws) this.ws.close();
        this.addTestResult('断开连接', true, '连接已关闭');
    }

    // 工具方法
    setupMessageHandler() {
        this.ws.on('message', (data) => {
            try {
                const msg = JSON.parse(data.toString());
                console.log(`📨 收到消息: act_id=${msg.act_id}, code=${msg.code}`);
            } catch (error) {
                console.error('消息解析失败:', error.message);
            }
        });
    }

    async makeHttpRequest(path, method, data) {
        return new Promise((resolve, reject) => {
            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path, method,
                headers: { 'Content-Type': 'application/json' }
            };

            const req = http.request(options, (res) => {
                let body = '';
                res.on('data', chunk => body += chunk);
                res.on('end', () => {
                    try {
                        resolve(JSON.parse(body));
                    } catch (error) {
                        resolve(body);
                    }
                });
            });

            req.on('error', reject);
            if (data) req.write(JSON.stringify(data));
            req.end();
        });
    }

    addTestResult(testName, success, message) {
        this.testResults.push({ test: testName, success, message, timestamp: new Date().toISOString() });
    }

    showResults() {
        console.log('\n📊 测试结果汇总:');
        console.log('='.repeat(50));

        let passed = 0, failed = 0;
        this.testResults.forEach((result, index) => {
            const status = result.success ? '✅' : '❌';
            console.log(`${status} ${index + 1}. ${result.test}: ${result.message}`);
            if (result.success) passed++; else failed++;
        });

        console.log(`\n📈 总计: ${this.testResults.length}, 通过: ${passed}, 失败: ${failed}`);
        console.log(`成功率: ${((passed / this.testResults.length) * 100).toFixed(1)}%`);

        if (failed === 0) {
            console.log('\n🎉 所有测试通过！');
        } else {
            console.log('\n⚠️ 部分测试失败，请检查相关功能');
        }
    }
}

// 主函数
async function main() {
    const args = process.argv.slice(2);
    const continueFrom = args.includes('--continue-from') ?
        parseInt(args[args.indexOf('--continue-from') + 1]) : 0;

    if (continueFrom > 0) {
        console.log(`🔄 从第${continueFrom}步继续执行...`);
    }

    const tester = new EnhancedClientTester();
    await tester.runTest();
}

if (require.main === module) {
    main().catch(console.error);
}

module.exports = EnhancedClientTester; 